/**
 * 
 */
package uk.ac.manchester.cs.graph.io;

import java.io.IOException;
import java.io.Writer;
import java.util.HashSet;

import uk.ac.manchester.cs.graph.Edge;
import uk.ac.manchester.cs.graph.Graph;

/**
 * Writes graphs in DOT format
 * 
 * @author Pavel Klinov
 *
 * pklinov@cs.man.ac.uk, pklinov@clarkparsia.com
 * 
 * Feb 4, 2009
 */
public class DOTWriterImpl<V,E> implements GraphWriter<V,E> {

	static String LFCR = System.getProperty( "line.separator" );
	
	private float m_width = 7;
	private float m_height = 7;
	private float m_nodeSize = 0.4f;
	private float m_fontSize = 10;
	private float m_edgeLength = 1;
	
	private GraphNodeWriter<V> m_nodeWriter = new GraphNodeWriter<V>() {
		
		public void write(V vertex, Writer out) throws IOException  {
			
			out.write( vertex.toString() );
		}
	};
	
	public void setSize(float width, float height) {
		
		m_width = width;
		m_height = height;
	}
	/* 
	 */
	public void write(Graph<V, E> graph, Writer writer) throws IOException {

		HashSet<Edge<V, E>> edges = new HashSet<Edge<V, E>>();
		
		writer.write(graph.isDirected() ? "digraph G {" : "graph G {"  );
		writer.write( "size=\"" + m_width + "," + m_height + "\";" + LFCR);
		
		for (V vertex : graph.getVertices()) {
			
			writeVertex(vertex, writer);
			writer.write( "[height=" + m_nodeSize + ", width=" + m_nodeSize + 
									", fontsize=" + m_fontSize + "];" + LFCR);
		}
		
		
		for( V vertex : graph.getVertices() ) {

			for( Edge<V, E> incident : graph.getIncidentEdges( vertex ) ) {

				if( !edges.contains( incident ) ) {

					writeVertex(incident.getStart(), writer);
					writer.write( graph.isDirected() ? " -> " : " -- " );
					writeVertex(incident.getEnd(), writer);
					writer.write( "[label=\"" + incident.getLabel() + "\", " );
					writer.write( "len=" + m_edgeLength + ", fontsize=" + m_fontSize + "];" + LFCR );
					edges.add( incident );
				}
			}
		}
		
		writer.write("}");
	}
	
	private void writeVertex(V vertex, Writer writer) throws IOException {
		
		writer.write("\"");
		m_nodeWriter.write( vertex, writer );
		writer.write("\" ");
	}
	
	public void setNodeSize(float size) {
		
		m_nodeSize = size;
	}
	public void setFontSize(float size) {
		
		m_fontSize = size;
	}
	public void setEdgeLength(float length) {
		
		m_edgeLength = length;
	}
	public void setNodeWriter(GraphNodeWriter<V> writer) {
		
		m_nodeWriter = writer;
	}
}
